package com.ljt.springsecuritylogin;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ljt.springsecuritylogin.domain.Users;
import com.ljt.springsecuritylogin.assembler.UserAssembler;
import com.ljt.springsecuritylogin.enums.Role;
import com.ljt.springsecuritylogin.service.UsersService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletConfig;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.util.Optional;

@RestController
@RequestMapping("/auth")
@RequiredArgsConstructor
public class AuthController {
    private final AuthenticationManager authenticationManager;
    private final JwtService jwtService;
    private final UsersService usersService;
    private final UserAssembler userAssembler;
    private final JwtConfig jwtConfig;
    private final ServletConfig servletConfig;
    private final PasswordEncoder passwordEncoder;


    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest, HttpServletResponse response) {
        String username = loginRequest.getUsername();
        String password = loginRequest.getPassword();
        // 校验参数
        if (password == null) {
            return ResponseEntity.badRequest().body("密码不能为空");
        }
        if (username == null) {
            return ResponseEntity.badRequest().body("用户名不能为空");
        }
        // 校验权限 无
        // 校验存在不需要

       authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
               username, password
       ));

        // 我需要在jwt里面还要放一个userId
        Users user = usersService.getOne(Wrappers.lambdaQuery(Users.class)
                .eq(Users::getUsername, username));

        String accessToken = jwtService.generateAccessToken(user);
        String refreshToken = jwtService.generateRefreshToken(user);
        Cookie cookie = new Cookie("refreshToken", refreshToken);
        cookie.setHttpOnly(true);//防止被JavaScript获取
        cookie.setPath("/auth/refresh");//TODO这个站点我们没有实现，我希望这个cookie只能被这个站点使用
        cookie.setMaxAge(Integer.parseInt(jwtConfig.getRefreshTokenExpiration()));//7d
        cookie.setSecure(true);//只有https
        response.addCookie(cookie);

        return ResponseEntity.ok(accessToken);
    }

    @PostMapping("/refresh")
    public ResponseEntity refresh(@CookieValue("refreshToken") String refreshToken){
        // 没有校验通过
        if (!jwtService.validateToken(refreshToken)){
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
        }

        Long userId = jwtService.getUserId(refreshToken);
        // 校验存在
        Users user = Optional.of(usersService.getById(userId)).orElseThrow(() -> new RuntimeException("用户不存在"));

        String accessToken = jwtService.generateAccessToken(user);

        return ResponseEntity.ok(accessToken);
    }

    @PostMapping("/validate")
    public boolean validate(@RequestHeader("Authorization") String token) {
        token = token.replace("Bearer ", "");
        return jwtService.validateToken(token);
    }

    @GetMapping("/me")
    public ResponseEntity me() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = (String) authentication.getPrincipal();

        Users user = Optional.of(usersService.getOne(Wrappers.lambdaQuery(Users.class).eq(Users::getUsername, username))).orElse(null);
        if (user == null) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
        }

        return ResponseEntity.ok(userAssembler.toUserDto(user));

    }

    @PostMapping("/register")
    public ResponseEntity<?> register(@RequestBody RegisterRequest registerRequest, HttpServletResponse response) {
        String username = registerRequest.getUsername();
        String password = registerRequest.getPassword();

        // 校验参数
        if (password == null || password.isEmpty()) {
            return ResponseEntity.badRequest().body("密码不能为空");
        }
        if (username == null || username.isEmpty()) {
            return ResponseEntity.badRequest().body("用户名不能为空");
        }

        // 校验用户名是否存在
        if (usersService.getOne(Wrappers.lambdaQuery(Users.class).eq(Users::getUsername, username)) != null) {
            return ResponseEntity.status(HttpStatus.CONFLICT).body("用户名已存在");
        }

        // 创建新用户
        Users user = new Users();
        user.setUsername(username);
        user.setPassword(passwordEncoder.encode(password)); // 注意：实际应使用加密存储密码
        user.setRole(Role.USER);

        usersService.save(user);

        // 自动登录并生成 Token //TODO 这个有没有必要要自己考虑
        authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
                username, password
        ));

        String accessToken = jwtService.generateAccessToken(user);
        String refreshToken = jwtService.generateRefreshToken(user);

        Cookie cookie = new Cookie("refreshToken", refreshToken);
        cookie.setHttpOnly(true);
        cookie.setPath("/auth/refresh");
        cookie.setMaxAge(Integer.parseInt(jwtConfig.getRefreshTokenExpiration())); // 7天
        cookie.setSecure(true);
        response.addCookie(cookie);

        return ResponseEntity.status(HttpStatus.CREATED).body(accessToken);
    }

    @ExceptionHandler(BadCredentialsException.class)
    public ResponseEntity<?> handleBadCredentialsException(Exception e) {
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
    }

}
